home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
EnigmA Amiga Run 1998 January
/
EnigmA AMIGA RUN 24 (1997)(G.R. Edizioni)(IT)[!][issue 1998-01 & 02].iso
/
LISTATI
/
main.c
< prev
next >
Wrap
C/C++ Source or Header
|
1997-11-11
|
10KB
|
270 lines
//**********************************************************************
//* *
//* Algoritmo per la decodifica di immagini IFF-ILBM *
//* *
//**********************************************************************
#include <exec/memory.h>
#include <exec/types.h>
#include <graphics/gfxbase.h>
#include <intuition/intuition.h>
#include <stdio.h>
#include <clib/exec_protos.h>
#include <clib/graphics_protos.h>
#include <clib/intuition_protos.h>
#define LIB_VERSION 39
#define DIM_MSG 20
#define NUM_MSG 10
#define DIM_RICERCA 2000
#define PUB_PULITA MEMF_PUBLIC|MEMF_CLEAR
#define ERR_MEMORIA 1
#define ERR_LIBS 2
#define ERR_TIPO_FILE 3
#define ID_IFF_FORM 0x464F524D //id header IFF (parola "FORM")
#define ID_IFF_ILBM 0x494C424D //id iff (parola "ILBM")
#define ID_IFF_BMHD 0x424D4844 //id IFF (parola "BMHD")
#define ID_IFF_CMAP 0x434D4150 //id iff (parola "CMAP")
#define ID_IFF_CAMG 0x43414D47 //id IFF (parola "CAMG")
#define ID_IFF_BODY 0x424F4459 //id iff (parola "BODY")
struct chunk {
ULONG id;
ULONG dimens;
UBYTE *buffer;
};// CMAP CAMG e BODY hanno praticamente la stessa struttura
struct chunk_bmhd {
ULONG id;
ULONG dimens;
UWORD lx_immagine;
UWORD ly_immagine;
UWORD x_bitmap;
UWORD y_bitmap;
UBYTE piani;
UBYTE decodifica;
UBYTE compressione;
UWORD colore_trasparente;
UBYTE x_aspetto_pixel;
UBYTE y_aspetto_pixel;
UWORD lx_schermo;
UWORD ly_schermo;
};
struct Library *intuibase=NULL,
*gfxbase=NULL;
struct chunk *cmap=NULL,
*camg=NULL,
*body=NULL;
struct chunk_bmhd bmhd; //BMHD ha grandezza fissa
// ########## dichiarazioni delle funzioni C usate #################
void Dealloca_Buffers();
ULONG Find_Id (ULONG,UBYTE*,ULONG);
struct chunk* File_To_Buffer(FILE*,ULONG,UBYTE*,ULONG);
int DecodeIff(FILE*);
void CloseLibs();
// ########## inizio listato ######################################
int main (int argc,char **argv)
{
FILE* finput = NULL;
int numero_files=1;
if ((intuibase=(struct Library*)OpenLibrary("intuition.library",LIB_VERSION))==NULL) return (ERR_LIBS);
// La funzione OpenLibrary apre una libreria di sistema.
// Accetta come argomenti il nome della libreria da aprire (UBYTE*) e la versione
// della stessa (ULONG).
// in caso di riuscita apertura della lireria restituisce l'indirizzo
// della struttura libreria appena allocata,viceversa 0 (NULL).
if ((gfxbase =(struct Library*)OpenLibrary("graphics.library",LIB_VERSION))==NULL)
{
CloseLibrary(intuibase);
return (ERR_LIBS);
}
for (numero_files=1;numero_files < argc;numero_files++)
if ((finput = fopen(argv[numero_files],"r")))
{
rewind ( finput );
DecodeIff ( finput );
fclose ( finput );
}
if (intuibase) CloseLibrary (intuibase);
if (gfxbase) CloseLibrary (gfxbase);
return(0);
}
void Dealloca_Buffers()
// Questa funzione dealloca i buffer puntati dalle nostre varibili globali,
// e successivamente dealloca le strutture chunk.
{
if (cmap->buffer) FreeMem(cmap->buffer,cmap->dimens);
if (camg->buffer) FreeMem(camg->buffer,camg->dimens);
if (body->buffer) FreeMem(body->buffer,body->dimens);
if (cmap) FreeMem(cmap,sizeof(struct chunk));
if (camg) FreeMem(camg,sizeof(struct chunk));
if (body) FreeMem(body,sizeof(struct chunk));
cmap=NULL;camg=NULL;body=NULL;
}
ULONG Find_Id(ULONG id, UBYTE* buffer,ULONG dimens_buffer)
// Questa funzione permette di cercare l'header in un buffer in memoria.
// "carattere" contiene la prima "lettera" che compone l'ID.
// Il resto del codice è una normale ricerca sequenziale.
// La funzione ritorna la posizione del chunk nel buffer (e quindi nel
// file) in caso di successo e il valore -1 in caso di insuccesso.
{
ULONG posiz=0;
UBYTE trovato=0;
UBYTE carattere=UBYTE(id>>24);
ULONG* indice=(ULONG*)buffer;
while ((posiz < dimens_buffer) & (!trovato))
{
if (carattere == (*indice>>24)) if (*indice == id) trovato=1;
((UBYTE*)indice)++;
if (!trovato) posiz++;
}
if (trovato) return(posiz);
return(-1);
}
struct chunk* File_To_Buffer(FILE *finput,ULONG id,UBYTE* buffer,ULONG dimens)
// Questa funzione crea il chunk vero e proprio trasferendo i dati dal
// file in memoria. La funzione ritorna il PUNTATORE alla struttura
// chunk in caso di successo, 0 (NULL) altrimenti.
{
struct chunk *appo=NULL;
ULONG posizione_id=0;
if ((appo=AllocMem(sizeof(struct chunk),MEMF_PUBLIC))==NULL) return(0);
posizione_id = Find_Id(id,buffer,dimens);
if (posizione_id == (-1)) goto errore_fatale;
fseek(finput,posizione_id,SEEK_SET);
fread((char*)&appo->id,1,4,finput);
fread((char*)&appo->dimens,1,4,finput);
if ((appo->buffer=AllocMem(appo->dimens,MEMF_PUBLIC))==NULL) goto errore_fatale;
fread((char*)appo->buffer,1,appo->dimens,finput);
return(appo);
errore_fatale: // La memoria è finita! Andate in pace.
FreeMem(appo,sizeof(struct chunk));
return(0);
}
int DecodeIff(FILE* finput)
{
struct Screen *schermo=NULL;
struct Window *finestra1=NULL,
*finestra2=NULL;
struct BitMap immagine;
ULONG i=0,j=0,r=0,g=0,b=0,riga=0;
UBYTE cicli=0,numero_bytes=0,bytes_per_riga=0,num_piano=0;
UBYTE* buffer=NULL;
UBYTE* appo=NULL;
UBYTE* indirizzo=NULL;
ULONG general=0;
ULONG dimens_buffer=DIM_RICERCA;
ULONG* camg_data=NULL;
fread ((char*)&general,1,4,finput);
if (general != ID_IFF_FORM) return(-2);
fread ((char*)&general,1,4,finput);
if (general<dimens_buffer) dimens_buffer=general-4;
if ((buffer=AllocMem(dimens_buffer,MEMF_PUBLIC))==NULL) return(-3);
fread ((char*)&general,1,4,finput);
if (general != ID_IFF_ILBM) return(-4);
rewind (finput);
fread (buffer,1,dimens_buffer,finput);
general=Find_Id(ID_IFF_BMHD,buffer,dimens_buffer);
if (general == -1 )
{ FreeMem(buffer,dimens_buffer);
return(ERR_TIPO_FILE);
}
fseek(finput,general,SEEK_SET);
fread((char *)&bmhd,1,sizeof(struct chunk_bmhd),finput);
cmap=File_To_Buffer(finput,ID_IFF_CMAP,buffer,dimens_buffer);
camg=File_To_Buffer(finput,ID_IFF_CAMG,buffer,dimens_buffer);
body=File_To_Buffer(finput,ID_IFF_BODY,buffer,dimens_buffer);
if ((cmap)&&(body)&&(camg))
{ if (bmhd.decodifica==1) goto errore_2;
if (bmhd.compressione>1) goto errore_2;
while((bmhd.lx_immagine % 16)) bmhd.lx_immagine++;
InitBitMap(&immagine,bmhd.piani,bmhd.lx_immagine,bmhd.ly_immagine);
for (i=0; i<bmhd.piani; i++)
if ((immagine.Planes[i]=AllocRaster(bmhd.lx_immagine,bmhd.ly_immagine))==NULL)
{ for (j=0;j<i;j++) FreeRaster(immagine.Planes[j],bmhd.lx_immagine,bmhd.ly_immagine);
goto errore_2;
}
camg_data=(ULONG*)camg->buffer;
if ((schermo=(struct Screen*)OpenScreenTags(NULL,
SA_Width,bmhd.lx_schermo, SA_Height,bmhd.ly_schermo,
SA_DisplayID,*camg_data, SA_Depth,bmhd.piani,
SA_FullPalette,TRUE, SA_Title,"IFF Reader V 1.0",
TAG_END,NULL))==NULL) goto errore_3;
appo=cmap->buffer;
for(i=0;i<(cmap->dimens/3);i++)
{
r=ULONG(*(appo++));
g=ULONG(*(appo++));
b=ULONG(*(appo++));
r+=r<<8;r+=r<<16;
g+=g<<8;g+=g<<16;
b+=b<<8;b+=b<<16;
SetRGB32(&schermo->ViewPort,i,r,g,b);
}
bytes_per_riga=bmhd.lx_immagine/8;
appo=body->buffer;
for (riga=0;riga<bmhd.ly_immagine;riga++)
{ for(num_piano=0;num_piano<bmhd.piani;num_piano++)
{ indirizzo=immagine.Planes[num_piano]+bytes_per_riga*riga;
if (bmhd.compressione==1)
{ numero_bytes=0;
while (numero_bytes<bytes_per_riga)
{ cicli=UBYTE(*(appo++));
if ((cicli)>127)
{ cicli=(-cicli)+1;
for(i=0;i<cicli;i++,numero_bytes++,indirizzo++) *indirizzo=*appo;
appo++;
}
else for(i=0;i<=cicli;i++,numero_bytes++) *(indirizzo++)=*(appo++);
}
}
else for(i=0;i<bytes_per_riga;i++) *(indirizzo++)=*(appo++);
}
}
if ((finestra2=(struct Window*)OpenWindowTags(NULL,
WA_Left ,0, WA_Top,0,
WA_Width,bmhd.lx_immagine, WA_Height,bmhd.ly_immagine,
WA_SmartRefresh,TRUE, WA_CustomScreen,schermo,
WA_Borderless,TRUE, WA_Title,"IFF Output",
WA_SuperBitMap,&immagine, TAG_END,NULL))==NULL) goto errore_3;
if ((finestra1=(struct Window*)OpenWindowTags(NULL,
WA_Left,0, WA_Top,0,
WA_Width,120, WA_Height,15,
WA_DetailPen,1, WA_BlockPen,0,
WA_IDCMP,IDCMP_CLOSEWINDOW, WA_CustomScreen,schermo,
WA_CloseGadget,TRUE, WA_DragBar,TRUE,
WA_Title,"<- Click ", TAG_END,NULL))==NULL) goto errore_3;
if(finestra1)Wait(1L << finestra1->UserPort->mp_SigBit);
}
errore_3:
if (finestra2) CloseWindow (finestra2);// Prima si chiudono sempre le
if (finestra1) CloseWindow (finestra1);// finestre poi lo schermo, altrimenti
if (schermo) CloseScreen (schermo); // si GURA!
for (i=0;i<bmhd.piani;i++)// Liberiamo i bitplanes
FreeRaster (immagine.Planes[i],bmhd.lx_immagine,bmhd.ly_immagine);
errore_2:
Dealloca_Buffers();
errore_1:
if (buffer) FreeMem(buffer,dimens_buffer);
return(0);
}